home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Internet / FWSaveAs.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  11.0 KB  |  392 lines  |  [TEXT/MPS ]

  1. //==============================================================================
  2. //
  3. //    File:                FWSaveAs.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //==============================================================================
  9. //
  10. //    Utility code for presenting a "Save As" dialog box.
  11. //    
  12. //    You need this when you need to export data and can choose between multiple 
  13. //    kinds. One might think that OpenDoc would handle it for you, but it doesn't 
  14. //    yet.
  15. //    
  16. //    Cyberdog disables the default OpenDoc saving code and requires each part to 
  17. //    implement SaveAs itself.
  18. //    
  19. //    Notes about the MacOS implementation:
  20. //    
  21. //    We have added a popup to the standard Save dialog. This requires us to 
  22. //    duplicate the system Save dialog, so you must localize it yourself. This is 
  23. //    unfortunate. A two-step Save interface (first ask format, then ask where) 
  24. //    would avoid this, and would perhaps be more useful for kinds like JPEG, 
  25. //    which require additional parameters. Or a hierarchical Save menu.
  26. //
  27.  
  28. #include "FWFrameW.hpp"
  29.  
  30. #ifndef FWSAVEAS_H
  31. #include "FWSaveAs.h"
  32. #endif
  33.  
  34. #ifndef FWSAVEAS_K
  35. #include "FWSaveAs.k"
  36. #endif
  37.  
  38. #ifndef FWENVDEF_H
  39. #include "FWEnvDef.h"
  40. #endif
  41.  
  42. #ifndef FWKIND_H
  43. #include "FWKind.h"
  44. #endif
  45.  
  46. #ifndef FWPART_H
  47. #include "FWPart.h"
  48. #endif
  49.  
  50. #ifndef FWCFMRES_H
  51. #include "FWCFMRes.h"
  52. #endif
  53.  
  54. #ifndef FWRESACC_H
  55. #include "FWResAcc.h"
  56. #endif
  57.  
  58. #ifndef FWRESSIN_H
  59. #include "FWResSin.h"
  60. #endif
  61.  
  62. #ifndef SOM_ODDispatcher_xh
  63. #include <Disptch.xh>
  64. #endif
  65.  
  66. //
  67. // MacOS-specific Framework and Platform Declarations
  68. //
  69.  
  70. #ifdef FW_BUILD_MAC
  71. #    ifndef __DIALOGS__
  72. #    include <Dialogs.h>
  73. #    endif
  74. #    ifndef SLLOCALE_H
  75. #    include "SLLocale.h"
  76. #    endif
  77. #    ifndef FWSESION_H
  78. #    include "FWSesion.h"
  79. #    endif
  80. #    ifndef __STANDARDFILE__
  81. #    include "StandardFile.h"
  82. #    endif
  83. #endif
  84.  
  85.  
  86. //------------------------------------------------------------------------------
  87. // Runtime Information
  88. //------------------------------------------------------------------------------
  89.  
  90. #ifdef FW_BUILD_MAC
  91. #pragma segment FW_OS_SaveAs
  92. #endif
  93.  
  94. //------------------------------------------------------------------------------
  95. // Utilities
  96. //------------------------------------------------------------------------------
  97. #pragma mark (Utilities)
  98.  
  99. #ifdef FW_BUILD_MAC
  100.  
  101. inline void FW_ExtractPascal (FW_CString s, Str255& ms)
  102. {
  103.     short byteLength = s.GetByteLength();
  104.     if (255 < byteLength) {
  105.         s.Truncate (255);
  106.         byteLength = 255;
  107.     }
  108.     
  109.     s.ExportPascal (ms);
  110.     
  111.     // may need to remove 1/2 of a double-byte character
  112.     FW_Locale locale;
  113.     s.GetLocale (locale);
  114.     if (byteLength && FW_CharIsDoubleByte ((char*)ms + 1, byteLength - 1, locale))
  115.             ms[0]--;
  116. }
  117.  
  118. #endif
  119.  
  120. template <class T>
  121. inline void FW_DeleteAll (FW_TOrderedCollection<T>& list)
  122. {
  123.     T* item = list.First();
  124.     while (item) {
  125.         list.Remove (item);
  126.         delete item;
  127.         item = list.First();
  128.     }
  129. }
  130. //------------------------------------------------------------------------------
  131. // Prototypes
  132. //------------------------------------------------------------------------------
  133. #pragma mark (Prototypes)
  134.  
  135. #ifdef FW_BUILD_MAC
  136.  
  137. pascal short     FW_PrivMacSaveAsDialogHook (short item, DialogPtr dialog, void* info_pointer);
  138. pascal Boolean     FW_PrivMacSaveAsFilterProc (DialogPtr dialog, EventRecord* event, short* item, void* info_pointer);
  139.  
  140. struct FW_SPrivMacSaveAsInfo {
  141.     short                                     item;
  142.     const FW_TOrderedCollection<FW_CString>* items;
  143.     ControlHandle                             popup;
  144. };
  145.  
  146. #endif
  147.  
  148. typedef pascal Boolean (*ModalFilterYDProcPtr)(
  149.     DialogPtr theDialog, EventRecord *theEvent, short *itemHit, void *yourDataPtr);
  150.  
  151. //------------------------------------------------------------------------------
  152. // Globals
  153. //------------------------------------------------------------------------------
  154. #pragma mark (Globals)
  155.  
  156. #ifdef FW_BUILD_MAC
  157.  
  158. RoutineDescriptor FW_gPrivMacSaveAsDialogHook = 
  159.     BUILD_ROUTINE_DESCRIPTOR (uppDlgHookYDProcInfo, FW_PrivMacSaveAsDialogHook);
  160.  
  161. RoutineDescriptor FW_gPrivMacSaveAsFilterProc = 
  162.     BUILD_ROUTINE_DESCRIPTOR (uppModalFilterYDProcInfo, FW_PrivMacSaveAsFilterProc);
  163.  
  164. const short FW_kPopupItemNumber = 13;
  165. const short FW_kSaveAsDialog = 29537;
  166. #endif
  167.  
  168. //------------------------------------------------------------------------------
  169. // FW_AskSaveAs
  170. //------------------------------------------------------------------------------
  171.  
  172. FW_Boolean FW_AskSaveAs (
  173.     short                                         resourceID         /* in */,
  174.     FW_CString                                     defaultName     /* in */,
  175.     FW_PFileSpecification&                         whereToSave        /* out */,
  176.     short&                                         kindChosen        /* out */)
  177. {
  178.     Boolean doSave = false;
  179.     FW_CString prompt;
  180.     short defaultKind = 1;
  181.     FW_TOrderedCollection<FW_CString> items;
  182.     
  183.     FW_SOMEnvironment ev;
  184.     FW_PSharedLibraryResourceFile partResources (ev);
  185.     FW_PResource saveAsResource (ev, partResources, resourceID, FW_kSaveAsResourceType);
  186.     FW_PResourceSink sink (ev, saveAsResource);
  187.     FW_CReadableStream s (sink);
  188.     
  189.     s >> prompt;
  190.     
  191.     FW_TRY {
  192.         // Now build a list of exportable kinds.
  193.         short count;
  194.         s >> count;
  195.         for (int i = 1; i <= count; i++) {
  196.             FW_CString name;
  197.             s >> name;
  198.             items.AddLast (FW_NEW (FW_CString, (name))); // XXX ugly
  199.         }
  200.         
  201.         // Put up the dialog
  202.         doSave = FW_AskSaveAsDynamic (items, defaultKind, prompt, defaultName, 
  203.             FW_kSaveAsDialog, whereToSave, kindChosen);
  204.     }
  205.     FW_CATCH_BEGIN
  206.     FW_CATCH_EVERYTHING() {
  207.         // Clean up after above FW_NEW (FW_CString) if anything fails.
  208.         FW_DeleteAll (items);
  209.         FW_THROW_SAME ();
  210.     }
  211.     FW_CATCH_END
  212.     
  213.     FW_DeleteAll (items);
  214.     return doSave;
  215. }
  216.  
  217. //------------------------------------------------------------------------------
  218. // FW_AskSaveAsDynamic
  219. //------------------------------------------------------------------------------
  220.  
  221. FW_Boolean FW_AskSaveAsDynamic (
  222.     const FW_TOrderedCollection<FW_CString>&    items             /* in */,
  223.     short                                         defaultItem     /* in */,
  224.     FW_CString                                     prompt             /* in */,
  225.     FW_CString                                     defaultName     /* in */,
  226.     short                                         resourceID         /* in */,
  227.     FW_PFileSpecification&                         whereToSave        /* out */,
  228.     short&                                         kindChosen        /* out */)
  229. {
  230. #ifdef FW_BUILD_MAC
  231.     Str255 cpfPrompt;
  232.     FW_ExtractPascal (prompt, cpfPrompt);
  233.     
  234.     Str255 cpfDefaultName;
  235.     FW_ExtractPascal (defaultName, cpfDefaultName);
  236.     
  237.     StandardFileReply reply;
  238.     Point where = { -1, -1 }; // auto-centered
  239.     
  240.     DlgHookYDUPP dlgHook = &FW_gPrivMacSaveAsDialogHook;
  241.     ModalFilterYDUPP filterProc = &FW_gPrivMacSaveAsFilterProc;
  242.     ActivationOrderListPtr activeList = nil;
  243.     ActivateYDUPP activate = nil;
  244.     
  245.     FW_SPrivMacSaveAsInfo info;
  246.     info.item = defaultItem;
  247.     info.items = &items;
  248.     info.popup = nil;
  249.     void* yourDataPtr = &info;
  250.     
  251.     FW_SOMEnvironment ev;
  252.     FW_PSharedLibraryResourceFile useResources (ev);
  253.     ::CustomPutFile (cpfPrompt, cpfDefaultName, &reply, resourceID, where, dlgHook, filterProc, activeList, activate, yourDataPtr);
  254.     
  255.     if (reply.sfGood == false)
  256.         return false;
  257.     
  258.     whereToSave = reply.sfFile;
  259.     kindChosen = info.item;
  260.     return true;
  261. #else
  262. #    error unimplemented
  263. #endif
  264. }
  265.  
  266. //------------------------------------------------------------------------------
  267. // FW_PrivMacSaveAsDialogHook
  268. //------------------------------------------------------------------------------
  269. // Handle clicks in the popup.
  270.  
  271. #ifdef FW_BUILD_MAC
  272.  
  273. pascal short FW_PrivMacSaveAsDialogHook (short item, DialogPtr dialog, void* info_pointer)
  274. {
  275.     
  276.     // Only filter the main dialog, not any nested dialogs.
  277.     long windowKind = ::GetWRefCon (dialog);
  278.     if (!windowKind == sfMainDialogRefCon)
  279.         return item;
  280.     
  281.     FW_SPrivMacSaveAsInfo* info = (FW_SPrivMacSaveAsInfo*) info_pointer;
  282.     
  283.     if (item == sfHookFirstCall) {
  284.         // Save popup reference
  285.         Handle h;
  286.         short dummy1;
  287.         Rect dummy2;
  288.         ::GetDialogItem (dialog, FW_kPopupItemNumber, &dummy1, &h, &dummy2);
  289.         info->popup = (ControlHandle) h;
  290.         // Insert items into the popup
  291.         // XXX This does not compile with STRICT_CONTROLS defined. Unfortunately Maxwell
  292.         // does not have interfaces for manipulating a control popup.
  293.         PopupPrivateDataHandle controlData = (PopupPrivateDataHandle) (*info->popup)->contrlData;
  294.         MenuHandle menu = (*controlData)->mHandle;
  295.         FW_TOrderedCollectionIterator<FW_CString> strings (info->items);
  296.         short index = 0;
  297.         for (FW_CString* s = strings.First(); strings.IsNotComplete(); s = strings.Next()) {
  298.             Str255 text;
  299.             FW_ExtractPascal (*s, text);
  300.             FW_ASSERT (text[0] != 0);
  301.             ::AppendMenu (menu, "\pMozilla");
  302.             index++;
  303.             ::SetMenuItemText (menu, index, text);
  304.         }
  305.         // Set current value
  306.         ::SetControlMaximum (info->popup, index);
  307.         ::SetControlValue (info->popup, info->item);
  308.         ::SetControlMinimum (info->popup, 1);
  309.     }
  310.     else if (item == sfHookLastCall)
  311.         info->item = ::GetControlValue (info->popup);
  312.     
  313.     return item;
  314. }
  315.  
  316. #endif
  317.  
  318. //------------------------------------------------------------------------------
  319. // FW_PrivMacSaveAsFilterProc
  320. //------------------------------------------------------------------------------
  321. // Handle events in the dialog.
  322.  
  323. /*
  324.     Inside Macintosh - Files:
  325.     
  326.     The Standard File Package contains an internal filter function that performs
  327.     some preliminary processing on each event it receives. If you provide a 
  328.     modal-dialog filter function, ModalDialog calls your filter function after 
  329.     it calls the internal Standard File Package filter function and before it 
  330.     sends the event to your dialog hook function.
  331.     
  332.     If your function returns a value of FALSE, ModalDialog processes the event 
  333.     through its own filters. If your function returns a value of TRUE, ModalDialog 
  334.     returns with no further action.
  335. */
  336.  
  337. #ifdef FW_BUILD_MAC
  338.  
  339. pascal Boolean FW_PrivMacSaveAsFilterProc (DialogPtr dialog, EventRecord* event, short* , void* )
  340. {
  341. //    FW_SPrivMacSaveAsInfo* info = (FW_SPrivMacSaveAsInfo*) info_pointer;
  342.     
  343.     // Although we have no use for it, just to be safe always pass the event on to
  344.     // the item handler.
  345.     FW_Boolean passToDialogHook = true;
  346.     
  347.     // Let OpenDoc handle idle and update events for windows other than the dialog.
  348.     FW_Boolean isDialogEvent = (DialogPtr) event->message == dialog;
  349.     FW_Boolean passToOpenDoc = ((event->what == nullEvent) || (isDialogEvent && (event->what == updateEvt || event->what == activateEvt)));
  350.     
  351.     if (passToOpenDoc) {
  352.         FW_TRY {
  353.             FW_SOMEnvironment ev;
  354.             FW_CSession::GetDispatcher(ev)->Dispatch (ev, event);
  355.         }
  356.         FW_CATCH_BEGIN
  357.         FW_CATCH_EVERYTHING() {
  358.         }
  359.         FW_CATCH_END
  360.     }
  361.     
  362.     return !passToDialogHook;
  363. }
  364.  
  365. #endif
  366.  
  367. //------------------------------------------------------------------------------
  368. // Obsolete
  369. //------------------------------------------------------------------------------
  370.  
  371. #if 0
  372.     // Read ODType strings and make a list of user names by calling 
  373.     // the OD namespace utilities.
  374.     const FW_TOrderedCollection<FW_CKind>* kinds = part->GetKinds();
  375.     FW_TOrderedCollectionIterator<FW_CKind> eachKind (kinds);
  376.     for (FW_CKind* kind = eachKind.First(); kind; kind = eachKind.Next()) {
  377.         if (kind->IsExportEnabled(ev)) {
  378.             ODType type = kind->GetType(ev);
  379.             // Get the english-(or whatever-) language name for the type
  380.             FW_CString name = type; // default if bindings are messed up
  381.             ODIText* odName = kODNULL;
  382.             if (::GetUserKindFromKind (FW_CSession::GetNameSpaceManager(ev), type, &odName))
  383.                 name = odName;
  384.             items.AddLast (FW_NEW (FW_CString, (name))); // XXX ugly
  385.             index++;
  386.             if (kind->IsPreferredKind(ev))
  387.                 defaultKind = index;
  388.         }
  389.     }
  390. #endif
  391.  
  392.